{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 问题：[[1,2],[3,4],[5,6]]一行代码展开该列表，得出[1,2,3,4,5,6]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "\n",
    "这个问题一拿到手，我们就应该想到使用序列的拼接，然后再去考虑如何归约，即把一系列值归约成一个。\n",
    "\n",
    "答案\n",
    ">>> from functools import reduce\n",
    ">>> reduce(lambda x, y: x + y, [[1,2],[3,4],[5,6]])\n",
    "问题中涉及的知识点：\n",
    "\n",
    "序列拼接\n",
    "归约函数\n",
    "知识点解析：\n",
    "\n",
    "使用+运算符实现序列的拼接\n",
    "\n",
    ">>> [1, 2] + [3, 4] # 输出 [1,2,3,4]\n",
    "+运算符两端都必须是序列类型才会实现序列的拼接。既然我们知道了拼接特性，那有什么办法实现[1, 2] + [3, 4] + [5, 6]呢？\n",
    "\n",
    "对可迭代对象的各个元素归约\n",
    "\n",
    "Python提供了几种归约函数：\n",
    "\n",
    "sum()\n",
    "functools.reduce(fn, alist)\n",
    "any(iterable)\n",
    "all(iterable)\n",
    "这些函数都可以把一个迭代对象归约为一个。\n",
    "\n",
    "sum(seq)函数很好理解，就是将序列中的数字对象做加法。\n",
    "\n",
    ">>> sum([1,2,3]) # 6\n",
    "下面仔细讲解一下reduce函数的用法。它有两个参数，第一个参数fn是一个接受两个参数的函数，第二个参数alist是一个列表。开始调用的时候，它会先把alist[0]，alist[1]传给fn，得到的结果作为下一次传给fn作为第一个参数，再从alistpop出下一个元素传给fn作为第二个参数。所以，这道题的归约步骤如下：\n",
    "\n",
    "取列表头两个元素给函数f(x,y) = x + y，即：[1, 2] + [3, 4] 得到结果 [1, 2, 3, 4]\n",
    "再用新的结果和下一个元素做函数操作[1, 2, 3, 4] + [5, 6] 得到结果 [1, 2, 3, 4, 5, 6]\n",
    "Tips: 你们可能注意到了，在调用reduce的时候，我导入了functools这个模块。在Python2的时候，reduce还是内置函数，但到了Python3的时候，它被移到functools这个模块里了，面试的时候不要忘记了。\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 延伸问题：简述any()和all()方法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "既然我们谈到了归约函数，那么这道题就放在这里给大家解答一下。这道题在各个公司的面试题中的出镜率还是比较高的。你可以在了解了归约函数的定义之后去理解这两个函数。\n",
    "\n",
    "答案：\n",
    "\n",
    "any(iterable)表示如果传入的可迭代对象有一个为True，这个函数就返回True。而all(iterable)表示如果`传入的可迭代对象所有的元素都为True，这个函数才返回True。\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 延伸问题：简述高阶函数的用法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "高阶函数使用起来非常简洁，这也是为什么大家喜欢用它的一个原因。一般情况下，如果能用内置函数，谁还自己去写一个呢？而且很多内置函数都是高度优化过的，这里提到的基本是很常用，所以大家尽量去熟记它们的用法。\n",
    "\n",
    "答案：\n",
    "\n",
    "高阶函数的定义是，即满足以下一个条件的函数：\n",
    "\n",
    "接受一个或多个函数作为输入\n",
    "输出一个函数\n",
    "在Python里，reduce，map，filter是常用的三个高阶函数。\n",
    "\n",
    "reduce(func, iterable)是每次只传入两个参数给函数，第一次使用可迭代对象中的前两个元素，后面每计算一次结果作为参数，再和可迭代对象中的下一个值传给函数进行计算，最终可规约为一个值。\n",
    "\n",
    "map(func, iterable)是将函数应用到每一个可迭代对象中的元素，返回一个迭代器。\n",
    "\n",
    "filter(func, iterable)是同样对序列中每个元素作用，但是传入的函数是一个返回布尔值的函数，然后过滤那些返回True的元素，也是返回一个迭代器。\n",
    "\n",
    ">>> from operator import add\n",
    ">>> list(map(lambda x: x+1, [1, 2, 3])) # [2, 3, 4]\n",
    ">>> list(filter(lambda x: x > 1, [1, 2, 3])) # [2, 3]\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 延伸问题：用高阶函数实现列表元素求和\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "答案：\n",
    "\n",
    ">>> reduce(lambda x, y: x + y, [1,2,3])\n",
    "知识点解析：\n",
    "\n",
    "对于数字组成的列表，用reduce求和和sum是一样的。\n",
    "\n",
    "Tips: 你也可以不用自己编写加法的匿名函数，可以直接使用operator这个模块里的add。就像这样使用reduce(add, [1,2,3])。但是，不要忘了导入。\n",
    "\n",
    "使用operator和reduce，还可以解决很多数学问题，比如实现阶乘。\n",
    "\n",
    ">>> from operator import mul\n",
    ">>> from functools import reduce\n",
    ">>> fact = reduce(mul, range(1, 10)) # 1*2*3*...*9\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 小结"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1.6、1.7、1.8 这三个小节中，我们继续讲解了一些基本内置的数据类型的常用操作：\n",
    "\n",
    "集合对象的元素增删，成员检测，去重，数学集合运算，…\n",
    "字符串对象的拼接，替换字符，分割，子字符串的计数，…\n",
    "还接触了很多Python的内置函数：\n",
    "\n",
    "关于排序：sorted()；\n",
    "有做归约的：reduce()（注意：这个函数已经移至operator模块），any()，all()，sum()；\n",
    "常用的高阶函数：map()和filter()。\n",
    "还有两个用于函数式设计的内置模块：operator和functools。operator主要用于标准运算符替代函数；functools主要用于高阶函数和可调用对象上的操作。\n",
    "\n",
    "我希望大家都能熟练掌握以上提到的知识点。因为这些都是一些基本知识点。在我帮大家了解知识点的基础上，希望大家也能多花点时间把上面提到的代码多敲打几遍去加深印象。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}